home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / news / readers / nn / nn6.4.patch6 < prev    next >
Encoding:
Text File  |  1990-06-25  |  59.6 KB  |  2,304 lines

  1.          This is an official patch to nn release 6.4
  2.          -------------------------------------------
  3.  
  4.                    PATCH #6
  5.  
  6.                 Priority: MEDIUM
  7.  
  8.  
  9. These patches fix a major and a few minor bugs in the 6.4 release, and
  10. add some new features based on patches and suggestions sent to me.
  11.  
  12. It provides the capability for 8 bit (ISO 8859) keyboard input.
  13.  
  14. It fixes a nasty bug which could cause nnmaster to die during expire
  15. (method 1) if all articles in the first group had been expired.
  16.  
  17. Problems related to the nn* utilities asking to add new groups to
  18. .newsrc if new-group-action is set to 4 or 5 have been solved by
  19. (silently) using action 3 (add new groups unconditionally), but
  20. without updating .newsrc or the LAST file.
  21.  
  22. NOTICE: The following change to entry macro semantics is *not*
  23.     backwards compatible.
  24.  
  25. Without this patch installed, only the commands :set, :unset, and
  26. :local will be executed prior to article collection if they occur at
  27. the beginning of an entry macro.
  28.  
  29. With this patch, ALL `:' commands at the beginning of an entry macro
  30. will be executed prior to article collection!  To postpone the
  31. execution of a `:' command until after article collection and showing
  32. the first menu page, a double `::' can be used, e.g.
  33.  
  34.     on entry comp.sources* alt.sources
  35.         :set cross-post on        # set before collection
  36.         :local auto-read-mode on    # set before showing menu
  37.         ::unset cross-post        # unset after collection
  38.     end
  39.  
  40. This change was done to make entry macros more powerful, but also to
  41. allow the new "start-up" macro (executed before entering the first
  42. group) to contain commands like ":show groups", e.g.
  43.  
  44.     on start-up
  45.         :show groups sequence
  46.     end
  47.  
  48. All changes are described in the updated RELEASE_NOTES file (read that
  49. for details about this patch).  Thanks to all who reported bugs and
  50. provided fixes.
  51.  
  52. To apply this patch, use nn's :patch command, or run this command from
  53. the shell in the root of the nn source tree:
  54.     patch -p0 < this-article
  55.  
  56.  
  57. ++Kim Storm
  58.  
  59. *** ./LAST/Makefile    Wed May 16 11:23:32 1990
  60. --- Makefile    Wed Jun 20 23:02:58 1990
  61. ***************
  62. *** 17,24 ****
  63.   # -----------------------------------------------------------------
  64.   #
  65.   #    make all    compile programs
  66. - #    make install    install programs
  67. - #    make initdb    initialize database
  68.   #    make clean    remove all make'd files from source directory
  69.   #
  70.   # no changes are needed below this line
  71. --- 17,22 ----
  72. ***************
  73. *** 44,63 ****
  74.   lint: ymakefile
  75.       $(MAKE) -f ymakefile lint
  76.   
  77. - install: ymakefile
  78. -     $(MAKE) $(MFLAGS) -f ymakefile install
  79. - initdb: ymakefile
  80. -     $(MAKE) $(MFLAGS) -f ymakefile initdb
  81. - online: ymakefile
  82. -     $(MAKE) $(MFLAGS) -f ymakefile online.manual
  83.   client: ymakefile
  84.       $(MAKE) $(MFLAGS) -f ymakefile client
  85. - install.client: ymakefile
  86. -     $(MAKE) $(MFLAGS) -f ymakefile install.client
  87.   
  88.   ymakefile: Makefile xmakefile config.h
  89.       cp xmakefile MF.c
  90. --- 42,49 ----
  91. *** ./LAST/account.c    Fri May  4 16:19:28 1990
  92. --- account.c    Fri Jun 22 23:22:27 1990
  93. ***************
  94. *** 26,31 ****
  95. --- 26,34 ----
  96.    *    The COST_PER_MINUTE should be the price per minute multiplied
  97.    *    by 100 (to allow prices like $0.03/minute).
  98.    *    The definitions below corresponds to 1 Kroner per minute.
  99. +  *
  100. +  *    If COST_PER_MINUTE is not defined (you can #undef it in config.h),
  101. +  *    a "Time used" rather than a "Cost" report is produced.
  102.    */
  103.   
  104.   #define ACCTLOG            /* */
  105. ***************
  106. *** 244,249 ****
  107. --- 247,255 ----
  108.              ((long)ses * COST_PER_MINUTE) / 100, COST_UNIT);
  109.       printf("%6ld %s",
  110.          (ac->ac_total * COST_PER_MINUTE) / 100, COST_UNIT);
  111. + #else
  112. +     printf("Time used this session: %d.%02d   Period total: %ld.%02ld",
  113. +        ses/60, ses%60, ac->ac_total/60, ac->ac_total%60);
  114.   #endif
  115.       if (ses >= 0 && ac->ac_quota > 0) {
  116.       r = ac->ac_quota - ac->ac_total/60;
  117. ***************
  118. *** 377,382 ****
  119. --- 383,391 ----
  120.       if (ck_policy >= 0) {
  121.   #ifdef AUTHORIZE
  122.       get_entry(acctf, caller, &ac);
  123. + #ifdef ACCOUNTING
  124. +     if (ac.ac_quota > 0 && ac.ac_quota < ac.ac_total/60) exit(4);
  125. + #endif
  126.       exit(policy_check(ac.ac_policy));
  127.   #else
  128.       exit(0);
  129. ***************
  130. *** 433,444 ****
  131.       if (add_usage > 0) {
  132.       put_entry(acctf, &ac);
  133.       if (report) {
  134. - #ifdef COST_PER_MINUTE
  135.           do_cost(&ac, add_usage);
  136. - #else
  137. -         strcpy(ac.ac_user, "Total:");
  138. -         do_report(&ac, 0);
  139. - #endif
  140.       }
  141.       fclose(acctf);
  142.   #ifdef ACCTLOG
  143. --- 442,448 ----
  144. *** ./LAST/admin.c    Tue May 29 18:36:16 1990
  145. --- admin.c    Fri Jun 22 22:14:12 1990
  146. ***************
  147. *** 25,30 ****
  148. --- 25,31 ----
  149.   
  150.   extern int group_completion();
  151.   
  152. + extern group_header *lookup_regexp();
  153.   
  154.   static get_cmd(prompt1, prompt2)
  155.   char *prompt1, *prompt2;
  156. ***************
  157. *** 814,824 ****
  158.    new_group:
  159.       if ((groupname = get_groupname()) == NULL) return;
  160.   
  161. !     gh = lookup(groupname);
  162. !     if (gh == NULL) {
  163. !     printf("No group named %s\n", groupname);
  164.       goto new_group;
  165. -     }
  166.   
  167.    have_group:
  168.       if (!use_nntp && init_group(gh)) {
  169. --- 815,822 ----
  170.    new_group:
  171.       if ((groupname = get_groupname()) == NULL) return;
  172.   
  173. !     if ((gh = lookup_regexp(groupname, "Enter", 0)) == NULL)
  174.       goto new_group;
  175.   
  176.    have_group:
  177.       if (!use_nntp && init_group(gh)) {
  178. *** ./LAST/answer.c    Tue Jun 12 11:46:24 1990
  179. --- answer.c    Mon Jun 25 11:14:41 1990
  180. ***************
  181. *** 21,26 ****
  182. --- 21,28 ----
  183.   export char *news_script    = NULL;
  184.   export char *mailer_program    = REC_MAIL;
  185.   export int  mailer_pipe_input    = 1;
  186. + export char *inews_program    = NULL;
  187. + export int  inews_pipe_input    = 1;
  188.   export char *editor_program    = NULL;
  189.   export char *spell_checker    = NULL;
  190.   
  191. ***************
  192. *** 231,236 ****
  193. --- 233,239 ----
  194.       char *args[10], *fn;
  195.       char route[512], *poster;
  196.       register char **ap = args;
  197. +     import int use_mmdf_folders;
  198.       import int novice;
  199.       import char *pager;
  200.   #ifdef NNTP
  201. ***************
  202. *** 243,248 ****
  203. --- 246,254 ----
  204.       return 1;
  205.       }
  206.   
  207. +     if (getenv("LOGNAME") == NULL)
  208. +     aux_param_str(param, "*LOGNAME", user_name());
  209.       if (strcmp(prog, "cancel") == 0) {
  210.       aux_param_str(param, "ART_ID", action);    /* article id for cancel */
  211.       aux_param_str(param, "GROUP", record);    /* group name for cancel */
  212. ***************
  213. *** 265,270 ****
  214. --- 271,279 ----
  215.       aux_param_bool(param, "MAILER_PIPE", mailer_pipe_input);
  216.       aux_param_int(param, "WAIT_PERIOD", response_check_pause);
  217.       aux_param_str(param, "DFLT_ANSW", response_dflt_answer);
  218. +     aux_param_str(param, "POST", inews_program);
  219. +     aux_param_bool(param, "POST_PIPE", inews_pipe_input);
  220. +     aux_param_str(param, "MMDF_SEP", use_mmdf_folders ? "\1\1\1\1" : "");
  221.   
  222.       if (current_group != NULL) {
  223.           aux_param_str(param, "*G", current_group->group_name);
  224. ***************
  225. *** 360,367 ****
  226.       }
  227.   
  228.       if (ah->flag & A_DIGEST) {
  229. !         if (digest.dg_from)
  230. !         news.ng_path = news.ng_from = digest.dg_from;
  231.           if (digest.dg_subj)
  232.           news.ng_subj = digest.dg_subj;
  233.       }
  234. --- 369,378 ----
  235.       }
  236.   
  237.       if (ah->flag & A_DIGEST) {
  238. !         if (digest.dg_from) {
  239. !         if (news.ng_reply) news.ng_from = news.ng_reply;
  240. !         news.ng_reply = digest.dg_from;
  241. !         }
  242.           if (digest.dg_subj)
  243.           news.ng_subj = digest.dg_subj;
  244.       }
  245. ***************
  246. *** 558,563 ****
  247. --- 569,575 ----
  248.           if (command != K_MAIL_OR_FORWARD || ftell(art) < ah->fpos)
  249.               fputs(included_mark, t);
  250.           prevnl = 0;
  251. +         if (c == NL) continue;
  252.           }
  253.           putc(c, t);
  254.       }
  255. ***************
  256. *** 699,704 ****
  257. --- 711,717 ----
  258.   
  259.       init_term(1);
  260.       visit_init_file(0, (char *)NULL);
  261. +     init_answer();
  262.       current_group = NULL;
  263.   
  264.       ngroups =
  265. ***************
  266. *** 868,870 ****
  267. --- 881,897 ----
  268.       return 1;
  269.   }
  270.   
  271. + init_answer()
  272. + {
  273. +     extern char *news_lib_directory;
  274. +     char buf[FILENAME + 5];
  275. + #ifndef INEWS_PATH
  276. + #define INEWS_PATH relative(news_lib_directory, "inews")
  277. + #endif
  278. +     if (inews_program == NULL) {
  279. +     sprintf(buf, "%s -h", INEWS_PATH);
  280. +     inews_program = copy_str(buf);
  281. +     }
  282. + }
  283. *** ./LAST/aux.sh    Tue Jun 12 11:46:27 1990
  284. --- aux.sh    Mon Jun 25 13:55:48 1990
  285. ***************
  286. *** 1,9 ****
  287.   
  288.   # PREFIX is inserted above this line during Make
  289.   
  290. - # make anne.jones happy (she is lost without a tty)
  291. - exec 3<&0
  292.   trap : 2 3
  293.   
  294.   PATH=/bin:$PATH
  295. --- 1,6 ----
  296. ***************
  297. *** 24,29 ****
  298. --- 21,30 ----
  299.   #    NOVICE        [expert]
  300.   #    WAIT_PERIOD     [response-check-pause]
  301.   #    RECORD        [mail/news-record]
  302. + #    MMDF_SEP    [mmdf-format = ^A^A^A^A]
  303. + #    POST        [inews]
  304. + #    POST_PIPE    [inews-pipe-input]
  305. + #    POSTER_ADR    Reply address for follow-ups
  306.   #    MAILER        [mailer]
  307.   #    MAILER_PIPE    [mailer-pipe-input]
  308.   #    DFLT_ANSW    [response-default-answer]
  309. ***************
  310. *** 298,303 ****
  311. --- 299,307 ----
  312.     {
  313.       # keep a copy of message in $RECORD (in mail format)
  314.       set `date`
  315. +     if [ -n "$MMDF_SEP" ] ; then
  316. +       echo "$MMDF_SEP"
  317. +     fi
  318.       if [ $3 -gt 9 ] ; then
  319.         echo From ${LOGNAME} $1 $2 $3 $4 $6 $7
  320.       else
  321. ***************
  322. *** 305,311 ****
  323.       fi
  324.       echo "From: ${LOGNAME}"
  325.       cat $FINAL
  326. !     echo ''
  327.     } >> "$RECORD"
  328.     fi
  329.   
  330. --- 309,315 ----
  331.       fi
  332.       echo "From: ${LOGNAME}"
  333.       cat $FINAL
  334. !     echo "$MMDF_SEP"
  335.     } >> "$RECORD"
  336.     fi
  337.   
  338. ***************
  339. *** 327,334 ****
  340.   
  341.       follow|post)
  342.         {
  343. !     $INEWS -h < $FINAL
  344. !     case $? in
  345.         0) sleep 60 ;;
  346.         *) echo $INEWS failed ;;
  347.       esac
  348. --- 331,344 ----
  349.   
  350.       follow|post)
  351.         {
  352. !     if ${POST_PIPE} ; then
  353. !       $POST < $FINAL
  354. !       x=$?
  355. !     else
  356. !       $POST $FINAL
  357. !       x=$?
  358. !     fi
  359. !     case $x in
  360.         0) sleep 60 ;;
  361.         *) echo $INEWS failed ;;
  362.       esac
  363. *** ./LAST/doc/RELEASE_NOTES    Tue Jun 12 11:46:32 1990
  364. --- doc/RELEASE_NOTES    Mon Jun 25 11:14:40 1990
  365. ***************
  366. *** 796,802 ****
  367. --- 796,889 ----
  368.   From:    pak@regent.e-technik.tu-muenchen.dbp.de (Peter A. Krauss)
  369.   Fixed:    Patch #5 [new parsing of string variables]
  370.   
  371. + Prog:    nnmaster -E1
  372. + Title:    If the first expired group's directory is empty, master may crash.
  373. + From:    robert@sysint.uucp (Robert Nelson)
  374. + Fixed:    Patch #6 [expire.c]
  375.   
  376. + Prog:    mini-inews
  377. + Title:    netinet/in.h included twice if network_database is defined.
  378. + From:    Peter A. Krauss <pak@regent.e-technik.tu-muenchen.de>
  379. + Fixed:    Patch #6 [inews/clientlib.c]
  380. + Prog:    nn
  381. + Title:    Patch #5 breaks init file parsing on some systems
  382. + From:    rob@dutncp9.TUDELFT.NL (Rob Kurver)
  383. +     srp@cgl.ucsf.EDU (Scott R. Presnell)
  384. + Fixed:    Patch #6 [global.h]
  385. + Prog:    aux
  386. + Title:    Patch #5 "exec 3<&0" in aux breaks editors on Apollos (at least)
  387. + From:    Ian Hoyle <ianh@bhpmrl.oz.au>
  388. + Fixed:    Patch #6 [answer.c aux.sh global.h -- LOGNAME is set instead]
  389. + Prog:    nn
  390. + Title:    Completion may incorrectly use col 80 of last line.
  391. + From:    Uwe Doering <gemini@geminix.mbx.sub.org> + fix
  392. + Fixed:    Patch #6 [term.c]
  393. + Prog:    all
  394. + Title:    file_exist does not check permissions correctly for "unusual" modes.
  395. + From:    Lars Henrik Mathiesen <thorinn@diku.dk>
  396. + Fixed:    Patch #6 [global.c - file_exist rewritten!]
  397. + Prog:    nn
  398. + Title:    entry-report-limit = 1 does not work for one article
  399. + From:    Jaap Vermeulen <jaap%sequent@relay.EU.net> + fix
  400. + Fixed:    Patch #6 [group.c]
  401. + Prog:    nn
  402. + Title:    Reply-To: in the digest header overrides subarticles' From: lines
  403. + From:    boomer@eleazar.dartmouth.edu (Rich Akerboom)
  404. + Fixed:    Patch #6 [answer.c]
  405. + Prog:    nncheck + nngrep + nntidy + nngoback + ???
  406. + Title:    new-group-action=4 causes problems with new groups.
  407. + From:    Peter Andersen <datpete@daimi.dk>
  408. +     mshappe@heights.CIT.CORNELL.EDU (Michael Shappe WR)
  409. + Fixed:    Patch #6 [newsrc.c nn.c]
  410. + Prog:    nn
  411. + Title:    "space" cannot be seen on key map displays
  412. + From:    pak@regent.e-technik.tu-muenchen.dbp.de (Peter A. Krauss)
  413. + Fixed:    Patch #6 [keymap.c -- now shown as "space"]
  414. + Prog:    aux
  415. + Title:    record files are not written in MMDF format when mmdf-format is set.
  416. + From:    gpvos@cs.vu.nl (Vos G P)
  417. + Fixed:    Patch #6 [answer.c aux.sh]
  418. + Prog:    nn
  419. + Title:    Name of unknown environment variables is printed using format %d
  420. + From:    weyh@ladwp.UUCP (Darwin C. Weyh)
  421. + Fixed:    Patch #6 [folder.c]
  422. + Prog:    nn
  423. + Title:    "pp" in reading mode marks previous (read) article unread
  424. + From:    Art Messenger <art@wilbur.coyote.trw.com>
  425. + Fixed:    Patch #6 [menu.c]
  426. + Prog:    nn
  427. + Title:    '*' in reading mode leaves current article unread
  428. + From:    Jaap Vermeulen <jaap%sequent@relay.EU.net>
  429. + Fixed:    Patch #6 [menu.c]
  430. + Prog:    nn
  431. + Title:    include-mark-blank-lines duplicates new-lines in included text
  432. + From:    Uwe Doering <gemini@geminix.mbx.sub.org> + fix
  433. + Fixed:    Patch #6 [answer.c]
  434. + Prog:    Makefile
  435. + Title:    initdb and install entries were left over from release 6.3
  436. + From:    rrr@hare.udev.cdc.com (Richard R Ragan)
  437. + Fixed:    Patch #6 [Makefile]
  438. + Prog:    nn, nnacct
  439. + Title:    AUTHORIZATION and QUOTA checks did not work as intended.
  440. + From:    KFS
  441. + Fixed:    Patch #6 [account.c execute.c]
  442.   New features since initial 6.4.0 release
  443.   ----------------------------------------
  444.   
  445. ***************
  446. *** 902,904 ****
  447. --- 989,1054 ----
  448.   Title:    New "kill-debug" variable to enable tracing of the auto-kill process.
  449.   From:    KFS
  450.   Added:    Patch #5 [kill.c variable.c nn.1]
  451. + Prog:    nnacct
  452. + Title:    "Time Used" reports are given if COST_PER_MINUTE is #undef'ed
  453. + From:    KFS on request from Tim Chown <tjc@ecs.soton.ac.uk>
  454. + Added:    Patch #6 [account.c]
  455. + Prog:    nn
  456. + Title:    8-bit cleanup (Keymaps are expanded to 8-bits if data-bits=8)
  457. + From:    marius@rhi.hi.is (Marius Olafsson) (adapted by KFS)
  458. + Added:    Patch #6 [global.h init.c keymap.c keymap.h term.c nn.1]
  459. +     If data-bits is 8, keyboard input will be 8-bit as well.
  460. +     Things like "map menu 0xc5 select" will now work.
  461. +     The positions 0x80-0x9f are reserved for function keys (so if
  462. +     they are used, they will overlay the function keys)!
  463. +     All national ISO 8859/* character sets are supported.
  464. +     PC codepages are not fully supported (they have national
  465. +     characters in the reserved area).
  466. + Prog:    nnmaster
  467. + Title:    New -h option to avoid nnmaster competing with rnews unbatching
  468. + From:    KFS on request from Roger Fujii <rmf@media.uucp>
  469. + Added:    Patch #6 [master.c nnmaster.8]
  470. + Prog:    nn
  471. + Title:    New "auto reading mode" controlled by auto-read-mode-limit variable.
  472. + From:    KFS on several requests for "rn compatibility"
  473. + Added:    Patch #6 [menu.c variable.c nn.1]
  474. + Prog:    nn
  475. + Title:    "G group" will now try regexp matching if group not found.
  476. + From:    KFS on request from Rich Akerboom <boomer@eleazar.dartmouth.edu>
  477. + Added:    Patch #6 [group.c nn.1]
  478. + Prog:    nn, aux
  479. + Title:    New variables: inews and inews-pipe-input (similar to mailer* vars)
  480. + From:    KFS on request from Jaap Vermeulen <jaap%sequent@relay.EU.net>
  481. + Added:    Patch #6 [answer.c aux.sh variable.c nn.1]
  482. + Prog:    nn
  483. + Title:    New "on start-up" construct executed before entering first group.
  484. + From:    KFS on request from Doug Walker <dougw@fdls.odag.or.gov>
  485. + Added:    Patch #6 [init.c macro.c nn.c nn.1]
  486. + Prog:    nn
  487. + Title:    New "on program ..." construct for program specific initializations
  488. + From:    KFS
  489. + Added:    Patch #6 [init.c nn.1]
  490. + Prog:    nn
  491. + Title:    New ":show groups sequence" variation equivalent to the Y command.
  492. + From:    KFS
  493. + Added:    Patch #6 [init.c nn.1]
  494. + Prog:    nn
  495. + Title:    Reading mode prompt contents changed (new var: new-style-read-prompt)
  496. + From:    KFS on request from karl@sugar.hackercorp.com (Karl Lehenbauer)
  497. + Added:    Patch #6 [menu.c more.c variable.c]
  498. + Prog:    nn
  499. + Title:    Header printed by :print now configurable via print-header-type
  500. + From:    KFS on request from Mikael.C.Kjaerulff@copenhagen.ncr.dk
  501. + Added:    Patch #6 [save.c variable.c nn.1]
  502. *** ./LAST/execute.c    Mon Apr 23 18:26:15 1990
  503. --- execute.c    Fri Jun 22 11:41:54 1990
  504. ***************
  505. *** 72,78 ****
  506.   
  507.       if (was_raw) raw();
  508.   
  509. !     return status != 0;
  510.   }
  511.   
  512.   
  513. --- 72,78 ----
  514.   
  515.       if (was_raw) raw();
  516.   
  517. !     return (status & 0xff) ? 0x100 : (status >> 8);
  518.   }
  519.   
  520.   
  521. *** ./LAST/expire.c    Tue Jun 12 11:46:33 1990
  522. --- expire.c    Thu Jun 14 22:07:46 1990
  523. ***************
  524. *** 70,78 ****
  525.       count++;
  526.       }
  527.       closedir(dirp);
  528. !     if (count)
  529. !     quicksort(article_list, count, article_number, sort_art_list);
  530. !     *art = 0;
  531.   
  532.       return article_list;
  533.   }
  534. --- 70,81 ----
  535.       count++;
  536.       }
  537.       closedir(dirp);
  538. !     if (article_list != NULL) {
  539. !     *art = 0;
  540. !     if (count > 1)
  541. !         quicksort(article_list, count, article_number, sort_art_list);
  542. !     }
  543.   
  544.       return article_list;
  545.   }
  546. *** ./LAST/folder.c    Tue May 29 18:36:25 1990
  547. --- folder.c    Wed Jun 20 21:59:25 1990
  548. ***************
  549. *** 88,94 ****
  550.           if ((cp = getenv(envar)) != NULL)
  551.               while (*cp) *dp++ = *cp++;
  552.           else {
  553. !             msg("Environment variable $(%d) not set", envar);
  554.               return 0;
  555.           }
  556.           }
  557. --- 88,94 ----
  558.           if ((cp = getenv(envar)) != NULL)
  559.               while (*cp) *dp++ = *cp++;
  560.           else {
  561. !             msg("Environment variable $(%s) not set", envar);
  562.               return 0;
  563.           }
  564.           }
  565. *** ./LAST/global.c    Tue Jun 12 11:46:35 1990
  566. --- global.c    Mon Jun 25 11:54:53 1990
  567. ***************
  568. *** 38,43 ****
  569. --- 38,44 ----
  570.   
  571.   export char version_id[32];
  572.   
  573. + export unsigned short user_eid;
  574.   export unsigned short user_id, group_id;
  575.   export int process_id;
  576.   export int who_am_i;
  577. ***************
  578. *** 58,63 ****
  579. --- 59,66 ----
  580.   {
  581.       int n;
  582.   
  583. +     if (gid == group_id) return 1;
  584.       for (n = 0; n < ngroups; ++n)
  585.       if (gidset[n] == gid) return 1;
  586.   
  587. ***************
  588. *** 178,187 ****
  589.   
  590.   #ifdef HAVE_MULTIGROUP
  591.       ngroups = getgroups(NGROUPS, gidset);    /* Get users's group set */
  592. -     group_id = gidset[0];    /* not used, but just in case... */
  593. - #else
  594. -     group_id = getgid();
  595.   #endif
  596.   
  597.       process_id = getpid();
  598.   
  599. --- 181,189 ----
  600.   
  601.   #ifdef HAVE_MULTIGROUP
  602.       ngroups = getgroups(NGROUPS, gidset);    /* Get users's group set */
  603.   #endif
  604. +     group_id = getegid();
  605. +     user_eid = geteuid();
  606.   
  607.       process_id = getpid();
  608.   
  609. ***************
  610. *** 355,362 ****
  611.   int size;
  612.   register FILE *f;
  613.   {
  614. !     register char c, *s = buf;
  615. !     register int n = size;
  616.       
  617.       while (--n > 0) {
  618.       c = getc(f);
  619. --- 357,364 ----
  620.   int size;
  621.   register FILE *f;
  622.   {
  623. !     register char *s = buf;
  624. !     register int c, n = size;
  625.       
  626.       while (--n > 0) {
  627.       c = getc(f);
  628. ***************
  629. *** 447,457 ****
  630. --- 449,467 ----
  631.   {
  632.       struct stat statb;
  633.       extern int errno;
  634. +     int mask;
  635.   
  636.       if (stat(name, &statb)) return 0;
  637.   
  638.       if (mode == NULL) return statb.st_mtime;
  639.   
  640. +     if (statb.st_uid == user_eid)
  641. +     mask = 0700;
  642. +     else if (group_access(statb.st_gid))
  643. +     mask = 0070;
  644. +     else
  645. +     mask = 0007;
  646.       while (*mode) {
  647.       switch (*mode++) {
  648.       case 'd':
  649. ***************
  650. *** 467,485 ****
  651.           }
  652.           break;
  653.       case 'r':
  654. !         if ((statb.st_mode & 0400) && statb.st_uid == user_id) continue;
  655. !         if ((statb.st_mode & 0040) && group_access(statb.st_gid)) continue;
  656. !             if ((statb.st_mode & 0004)) continue;
  657.           break;
  658.       case 'w':
  659. !         if ((statb.st_mode & 0200) && statb.st_uid == user_id) continue;
  660. !         if ((statb.st_mode & 0020) && group_access(statb.st_gid)) continue;
  661. !             if ((statb.st_mode & 0002)) continue;
  662.           break;
  663.       case 'x':
  664. !         if ((statb.st_mode & 0100) && statb.st_uid == user_id) continue;
  665. !         if ((statb.st_mode & 0010) && group_access(statb.st_gid)) continue;
  666. !             if ((statb.st_mode & 0001)) continue;
  667.           break;
  668.       }
  669.       errno = EACCES;
  670. --- 477,489 ----
  671.           }
  672.           break;
  673.       case 'r':
  674. !         if (statb.st_mode & mask & 0444) continue;
  675.           break;
  676.       case 'w':
  677. !         if (statb.st_mode & mask & 0222) continue;
  678.           break;
  679.       case 'x':
  680. !         if (statb.st_mode & mask & 0111) continue;
  681.           break;
  682.       }
  683.       errno = EACCES;
  684. ***************
  685. *** 581,586 ****
  686. --- 585,592 ----
  687.       if (who_am_i == I_AM_EXPIRE) return "X";
  688.   
  689.       if (user == NULL) {
  690. +     extern char *getlogin();
  691. +     if (user = getlogin()) return user;
  692.       pw = getpwuid((int)user_id);
  693.       if (pw == NULL) user = "?";
  694.       user = copy_str(pw->pw_name);
  695. *** ./LAST/global.h    Sun Apr 29 23:11:59 1990
  696. --- global.h    Fri Jun 22 22:51:47 1990
  697. ***************
  698. *** 225,227 ****
  699. --- 225,240 ----
  700.   
  701.   #define    Loop_Groups_Newsrc(gh) \
  702.       for (gh = rc_sequence; gh; gh = gh->newsrc_seq)
  703. + /* 8 bit support (ISO 8859/...) */
  704. + #ifdef HAVE_8BIT_CTYPE
  705. + #ifdef isascii
  706. + #undef isascii
  707. + #endif
  708. + #define isascii(c)    1
  709. + #define iso8859(c)    (isprint(c))
  710. + #else
  711. + #define iso8859(c)    ((c) & 0x60)
  712. + #endif
  713. *** ./LAST/group.c    Tue Jun 12 11:46:35 1990
  714. --- group.c    Mon Jun 25 11:54:16 1990
  715. ***************
  716. *** 10,15 ****
  717. --- 10,16 ----
  718.   #include "term.h"
  719.   #include "menu.h"
  720.   #include "keymap.h"
  721. + #include "regexp.h"
  722.   #ifdef HAVE_SYSLOG
  723.   #include <syslog.h>
  724.   #endif
  725. ***************
  726. *** 268,274 ****
  727.       }
  728.   
  729.       if (entry_message_limit &&
  730. !         (n = gh->last_db_article - gh->current_first) >= entry_message_limit) {
  731.           clrdisp();
  732.           printf("Reading %s: %ld articles...", gh->group_name, (long)n);
  733.       } else
  734. --- 269,275 ----
  735.       }
  736.   
  737.       if (entry_message_limit &&
  738. !         (n = gh->last_db_article - gh->current_first + 1) >= entry_message_limit) {
  739.           clrdisp();
  740.           printf("Reading %s: %ld articles...", gh->group_name, (long)n);
  741.       } else
  742. ***************
  743. *** 356,362 ****
  744. --- 357,418 ----
  745.       return menu_cmd;
  746.   }
  747.   
  748. + static l_re_query(pr, gh)
  749. + char *pr;
  750. + group_header *gh;
  751. + {
  752. +     if (pr == NULL) return 1;
  753. +     prompt("\1%s\1 %s ? ", pr, gh->group_name);
  754. +     return yes(0);
  755. + }
  756. + group_header *lookup_regexp(name, pr, flag)
  757. + char *name, *pr;
  758. + int flag;    /* 1=>seq order, 2=>msg(err) */
  759. + {
  760. +     group_header *gh;
  761. +     regexp *re;
  762. +     int y, any;
  763. +     char *err;
  764. +     if (gh = lookup(name)) return gh;
  765. +     if ((re = regcomp(name)) == NULL) return NULL;
  766. +     y = any = 0;
  767. +     
  768. +     if (flag & 1)
  769. +     Loop_Groups_Sequence(gh) {
  770. +         if (gh->last_db_article == 0) continue;
  771. +         if (gh->last_db_article < gh->first_db_article) continue;
  772. +         if (!regexec(re, gh->group_name)) continue;
  773. +         any++;
  774. +         if (y = l_re_query(pr, gh)) goto ok;
  775. +     }
  776. +     Loop_Groups_Sorted(gh) {
  777. +     if (flag & 1) {
  778. +         if (gh->master_flag & M_IGNORE_GROUP) continue;
  779. +         if (gh->group_flag & G_SEQUENCE) continue;
  780. +     }
  781. +     if (!regexec(re, gh->group_name)) continue;
  782. +     any++;
  783. +     if (y = l_re_query(pr, gh)) goto ok;
  784. +     }
  785. +     err = any ? "No more groups" : "No group";
  786. +     if (flag & 2)
  787. +     msg("%s matching `%s'", err, name);
  788. +     else
  789. +     printf("\n\r%s matching `%s'\n\r", err, name);
  790.   
  791. +     gh = NULL;
  792. +     
  793. +  ok:
  794. +     freeobj(re);
  795. +     return y < 0 ? NULL : gh;
  796. + }
  797.   goto_group(command, ah, access_mode)
  798.   int command;
  799.   article_header *ah;
  800. ***************
  801. *** 584,593 ****
  802.       break;
  803.       }
  804.   
  805. !     if ((gh = lookup(answer)) == NULL) {
  806. !     msg("No group named %s", answer);
  807.       goto_return(ME_NO_REDRAW);
  808. -     }
  809.   
  810.   
  811.    get_first:
  812. --- 640,647 ----
  813.       break;
  814.       }
  815.   
  816. !     if ((gh = lookup_regexp(answer, "Goto", 3)) == NULL)
  817.       goto_return(ME_NO_REDRAW);
  818.   
  819.   
  820.    get_first:
  821. ***************
  822. *** 961,966 ****
  823. --- 1015,1021 ----
  824.       if (amount <= 1 && gh->unread_count <= 0) continue;
  825.       if (amount == 0 && (gh->group_flag & G_UNSUBSCRIBED)) continue;
  826.       if (amount == 3 && (gh->group_flag & G_UNSUBSCRIBED) == 0) continue;
  827. +     if (amount == 4 && (gh->group_flag & G_SEQUENCE) == 0) continue;
  828.   
  829.       if (disp_group(gh) < 0) break;
  830.       }
  831. *** ./LAST/inews/clientlib.c    Wed May 16 11:23:37 1990
  832. --- inews/clientlib.c    Tue Jun 19 20:19:59 1990
  833. ***************
  834. *** 23,29 ****
  835. --- 23,35 ----
  836.   #include <sys/types.h>
  837.   #endif
  838.   #include <sys/socket.h>
  839. + #ifdef FOR_NN
  840. + #if !defined(NETWORK_DATABASE) || defined(NETWORK_BYTE_ORDER)
  841.   #include <netinet/in.h>
  842. + #endif
  843. + #else
  844. + #include <netinet/in.h>
  845. + #endif
  846.   #ifndef EXCELAN
  847.   # include <netdb.h>
  848.   #endif not EXCELAN
  849. *** ./LAST/inews/conf.h    Tue May  1 22:31:35 1990
  850. --- inews/conf.h    Fri Jun 22 21:49:52 1990
  851. ***************
  852. *** 98,103 ****
  853. --- 98,109 ----
  854.   #define index strchr
  855.   #endif
  856.   
  857. + #ifdef NO_BZERO
  858. + #ifndef USG
  859. + #define USG
  860. + #endif
  861. + #endif
  862.   /*
  863.    *  Sanity checks (You know.  Checks you get from Sanity Claus)
  864.    */
  865. *** ./LAST/init.c    Tue Jun 12 11:46:37 1990
  866. --- init.c    Thu Jun 21 22:16:49 1990
  867. ***************
  868. *** 58,64 ****
  869.   {
  870.       if (cmd == NULL) return cmd;
  871.   
  872. !     while (*cmd && isspace(*cmd)) cmd++;
  873.       if (*cmd == NUL || *cmd == NL) return NULL;
  874.   
  875.       return cmd;
  876. --- 58,64 ----
  877.   {
  878.       if (cmd == NULL) return cmd;
  879.   
  880. !     while (*cmd && isascii(*cmd) && isspace(*cmd)) cmd++;
  881.       if (*cmd == NUL || *cmd == NL) return NULL;
  882.   
  883.       return cmd;
  884. ***************
  885. *** 94,100 ****
  886.       if (argc <= i)
  887.       if (cmd = argvec[argc])
  888.           while (argc <= i) {
  889. !         while (*cmd && !isspace(*cmd)) cmd++;
  890.           if (*cmd == NUL) {
  891.               argc = MAXARG;
  892.               break;
  893. --- 94,100 ----
  894.       if (argc <= i)
  895.       if (cmd = argvec[argc])
  896.           while (argc <= i) {
  897. !         while (*cmd && (!isascii(*cmd) || !isspace(*cmd))) cmd++;
  898.           if (*cmd == NUL) {
  899.               argc = MAXARG;
  900.               break;
  901. ***************
  902. *** 534,539 ****
  903. --- 534,545 ----
  904.           if ARG(mode_arg, "unsub")
  905.           group_overview(3);
  906.           else
  907. +         if ARG(mode_arg, "subscr")
  908. +         group_overview(4);
  909. +         else
  910. +         if ARG(mode_arg, "sequence")
  911. +         group_overview(-1);
  912. +         else
  913.           group_overview(0);
  914.   
  915.           break;
  916. ***************
  917. *** 641,647 ****
  918.           bind_to = K_function(argv(1)[1] - '0');
  919.           else {
  920.           bind_to = parse_key(argv(1) + 1);
  921. !         if (bind_to <= 0x80) break; /* not pretty! */
  922.           }
  923.   
  924.           for (i = 2, mb = multi_buffer; argv(i); i++)
  925. --- 647,653 ----
  926.           bind_to = K_function(argv(1)[1] - '0');
  927.           else {
  928.           bind_to = parse_key(argv(1) + 1);
  929. !         if (bind_to < K_up_arrow || bind_to > K_right_arrow) break;
  930.           }
  931.   
  932.           for (i = 2, mb = multi_buffer; argv(i); i++)
  933. ***************
  934. *** 706,712 ****
  935.   
  936.           if (code == K_EQUAL_KEY) {
  937.           if (argv(4))
  938. !             code = menu_key_map[parse_key(argv(4))];
  939.           else
  940.               goto mac_err;
  941.           } else
  942. --- 712,718 ----
  943.   
  944.           if (code == K_EQUAL_KEY) {
  945.           if (argv(4))
  946. !             code = more_key_map[parse_key(argv(4))];
  947.           else
  948.               goto mac_err;
  949.           } else
  950. ***************
  951. *** 805,810 ****
  952. --- 811,838 ----
  953.           for (i = 2; argv(i) != NULL; i++)
  954.           if (strcmp(argv(2), local_host) == 0) return;
  955.           break;
  956. +     }
  957. +     CASE( "program" ) {
  958. +         extern char *pname;
  959. +         char *pname1;
  960. +         int i;
  961. +         for (pname1 = pname; *pname1 == 'n'; pname1++);
  962. +         
  963. +         for (i = 2; argv(i) != NULL; i++) {
  964. +         if (strcmp(argv(i), pname) == 0) return;
  965. +         if (pname1[0] && strcmp(argv(i), pname1) == 0) return;
  966. +         }
  967. +         break;
  968. +     }
  969. +     CASE( "start-up" ) {
  970. +         import char *start_up_macro;
  971. +         char *parse_enter_macro();
  972. +         start_up_macro = parse_enter_macro(f, NL);
  973. +         return;
  974.       }
  975.   
  976.       goto on_err;
  977. *** ./LAST/keymap.c    Tue May 22 12:53:42 1990
  978. --- keymap.c    Wed Jun 20 20:22:48 1990
  979. ***************
  980. *** 8,15 ****
  981. --- 8,40 ----
  982.   #include "keymap.h"
  983.   #include "term.h"
  984.   
  985. + import int data_bits;
  986.   
  987.   /*
  988. +  * KEY MAP LAYOUT:
  989. +  *    128 normal ASCII chars
  990. +  *    0200 -- unused
  991. +  *    4 arrow keys #up/down/left/right
  992. +  *    10 multi keys #0-#9
  993. +  *    17 spare keys
  994. +  *    95 national 8-bit characters (8859/x)
  995. +  *    0377 is unused (since we must be able to test c<KEY_MAP_SIZE)
  996. +  *
  997. +  *    The encoding of the keymap arrays are performed in
  998. +  *    keymap.c (initialization + key_name/parse_key)
  999. +  */
  1000. + /* in keymap.h, MULTI_KEYS include ARROW_KEYS for term.c */
  1001. + #undef MULTI_KEYS
  1002. + #define NORMAL_KEYS    129    /* include 0200 for convenience */
  1003. + #define ARROW_KEYS    4
  1004. + #define MULTI_KEYS    10
  1005. + #define SPARE_KEYS    17
  1006. + #define NATIONAL_KEYS    96
  1007. + #define KEY_MAP_SIZE    255
  1008. + /*
  1009.    * standard keyboard mapping for more()
  1010.    *
  1011.    *    redraw            ^L, ^R
  1012. ***************
  1013. *** 522,527 ****
  1014. --- 547,556 ----
  1015.       register struct command_name_map *cnmp;
  1016.   
  1017.       for (c = 0; c < KEY_MAP_SIZE; c++) global_key_map[c] = c;
  1018. +     for (c = NORMAL_KEYS+ARROW_KEYS; c < KEY_MAP_SIZE; c++) {
  1019. +     menu_key_map[c] = K_UNBOUND;
  1020. +     more_key_map[c] = K_UNBOUND;
  1021. +     }
  1022.   
  1023.       for (cnmp = command_name_map; cnmp->cmd_name; cnmp++);
  1024.       name_map_size = cnmp - command_name_map;
  1025. ***************
  1026. *** 650,656 ****
  1027.       int x;
  1028.   
  1029.       if (str[1] == NUL)
  1030. !     return str[0] & 0177;
  1031.   
  1032.       if (str[0] == '^')
  1033.       if (str[1] == '?')
  1034. --- 679,685 ----
  1035.       int x;
  1036.   
  1037.       if (str[1] == NUL)
  1038. !     return (data_bits < 8) ? (str[0] & 0177) : str[0];
  1039.   
  1040.       if (str[0] == '^')
  1041.       if (str[1] == '?')
  1042. ***************
  1043. *** 667,678 ****
  1044.       else
  1045.           sscanf(str, "%d", &x);
  1046.   
  1047. !     return x & 0177;
  1048.       }
  1049.   
  1050.       if (str[0] == '#' && isdigit(str[1]))
  1051.       return K_function(str[1] - '0');
  1052.   
  1053.       if (strcmp(str, "up") == 0)
  1054.       return K_up_arrow;
  1055.   
  1056. --- 696,709 ----
  1057.       else
  1058.           sscanf(str, "%d", &x);
  1059.   
  1060. !     return x;
  1061.       }
  1062.   
  1063.       if (str[0] == '#' && isdigit(str[1]))
  1064.       return K_function(str[1] - '0');
  1065.   
  1066. +     if (str[0] == '#') str++;
  1067. +     
  1068.       if (strcmp(str, "up") == 0)
  1069.       return K_up_arrow;
  1070.   
  1071. ***************
  1072. *** 693,701 ****
  1073.   char *key_name(c)
  1074.   key_type c;
  1075.   {
  1076. !     static char buf[3];
  1077.   
  1078. !     if (c & 0200) {
  1079.       switch (c) {
  1080.        case K_up_arrow:
  1081.           return "up";
  1082. --- 724,732 ----
  1083.   char *key_name(c)
  1084.   key_type c;
  1085.   {
  1086. !     static char buf[10];
  1087.   
  1088. !     if (c >= NORMAL_KEYS && c <= (KEY_MAP_SIZE-NATIONAL_KEYS)) {
  1089.       switch (c) {
  1090.        case K_up_arrow:
  1091.           return "up";
  1092. ***************
  1093. *** 707,718 ****
  1094.           return "right";
  1095.        default:
  1096.           buf[0] = '#';
  1097. !         buf[1] = (c - K_function(0)) + '0';
  1098.           buf[2] = NUL;
  1099.           goto out;
  1100.       }
  1101.       }
  1102.   
  1103.       if (c < SP) {
  1104.       buf[0] = '^';
  1105.       buf[1] = c + '@';
  1106. --- 738,753 ----
  1107.           return "right";
  1108.        default:
  1109.           buf[0] = '#';
  1110. !         buf[1] = (c - K_function(0))
  1111. !         + (c >= NORMAL_KEYS+ARROW_KEYS+MULTI_KEYS) ? 'A' : '0';
  1112.           buf[2] = NUL;
  1113.           goto out;
  1114.       }
  1115.       }
  1116.   
  1117. +     if (c == SP)
  1118. +     return "space";
  1119.       if (c < SP) {
  1120.       buf[0] = '^';
  1121.       buf[1] = c + '@';
  1122. ***************
  1123. *** 722,727 ****
  1124. --- 757,767 ----
  1125.   
  1126.       if (c == 0177) {
  1127.       strcpy(buf, "^?");
  1128. +     goto out;
  1129. +     }
  1130. +     if (data_bits < 8 && c >= NORMAL_KEYS) {
  1131. +     sprintf(buf, "0x%02x", c);
  1132.       goto out;
  1133.       }
  1134.   
  1135. *** ./LAST/keymap.h    Tue May 22 12:53:42 1990
  1136. --- keymap.h    Wed Jun 13 15:56:09 1990
  1137. ***************
  1138. *** 104,118 ****
  1139.   #define    K_MACRO            0x0100 /* call macro            */
  1140.   #define    K_ARTICLE_ID        0x0200 /* article id in lower part    */
  1141.   
  1142.   
  1143. ! /*
  1144. !  * KEY MAP SIZE is:
  1145. !  *   (128 normal chars) + (0200) + (4 arrow keys) + (10 function keys)
  1146. !  */
  1147. ! #define MULTI_KEYS    (1 + 4 + 10)
  1148. ! #define KEY_MAP_SIZE    (128 + MULTI_KEYS)
  1149.   
  1150.   /* restrictions */
  1151.   
  1152. --- 104,112 ----
  1153.   #define    K_MACRO            0x0100 /* call macro            */
  1154.   #define    K_ARTICLE_ID        0x0200 /* article id in lower part    */
  1155.   
  1156. + /* keymap definitions from keymap.c */
  1157.   
  1158. ! #define MULTI_KEYS    15
  1159.   
  1160.   /* restrictions */
  1161.   
  1162. *** ./LAST/macro.c    Tue Jun 12 11:46:40 1990
  1163. --- macro.c    Wed Jun 20 22:30:08 1990
  1164. ***************
  1165. *** 12,17 ****
  1166. --- 12,18 ----
  1167.   export int get_from_macro = 0;
  1168.   export int macro_debug = 0;
  1169.   export char *dflt_enter_macro = NULL;
  1170. + export char *start_up_macro = NULL;
  1171.   
  1172.   #define M_DUMMY        0    /* do nothing (end of branch)     */
  1173.   
  1174. ***************
  1175. *** 263,271 ****
  1176. --- 264,278 ----
  1177.       if (*lp == ':') {
  1178.           lp++;
  1179.           if (initial_set_commands) {
  1180. + #ifdef REL_640_COMPAT
  1181.           if (strncmp(lp, "local",  5) == 0 ||
  1182.               strncmp(lp, "set",    3) == 0 ||
  1183.               strncmp(lp, "unset",  5) == 0) {
  1184. + #else
  1185. +             if (lp[0] == ':')
  1186. +             lp++;
  1187. +         else {
  1188. + #endif
  1189.               m_new(M_SET_COMMAND);
  1190.               m->m_string = copy_str(lp);
  1191.               break;
  1192. ***************
  1193. *** 428,433 ****
  1194. --- 435,445 ----
  1195.   m_invoke(n)
  1196.   int n;
  1197.   {
  1198. +     if (n == -2) {
  1199. +     n = NMACRO;
  1200. +     if ((macro[n] = (struct macro *)start_up_macro) == NULL)
  1201. +         return;
  1202. +     } else
  1203.       if (n < 0) {
  1204.       n = NMACRO;
  1205.       if ((macro[n] = (struct macro *)(current_group->enter_macro)) == NULL)
  1206. *** ./LAST/man/nn.1.B    Tue Jun 12 11:46:45 1990
  1207. --- man/nn.1.B    Mon Jun 25 15:18:12 1990
  1208. ***************
  1209. *** 276,281 ****
  1210. --- 276,285 ----
  1211.   .TP
  1212.   \fIletter\fP
  1213.   The answer is taken to be the name of a newsgroup.
  1214. + If a news group with the given name does not exist, \fInn\fP will
  1215. + treat the answer as a regular expression and locate the first group
  1216. + in the presentation sequence (or among all groups) whose name matches
  1217. + the expression.
  1218.   .TP
  1219.   .I +
  1220.   .br
  1221. ***************
  1222. *** 824,829 ****
  1223. --- 828,835 ----
  1224.   group, depending on \fImode\fP: \fBall\fP (list the number of unread
  1225.   articles in all groups including groups which you have unsubscribed
  1226.   to), \fBtotal\fP (list the total number of articles in all existing
  1227. + groups), \fBsequence\fP (list unread groups in presentation sequence
  1228. + order), \fBsubscr\fP (list all subscribed
  1229.   groups), \fBunsub\fP (list unsubscribed groups only).  Any other
  1230.   \fImode\fP results in a listing of the number of unread articles in
  1231.   all subscribed groups including those you have suppressed with the `!'
  1232. *** ./LAST/man/nn.1.C    Tue Jun 12 11:46:48 1990
  1233. --- man/nn.1.C    Mon Jun 25 15:18:12 1990
  1234. ***************
  1235. *** 194,199 ****
  1236. --- 194,209 ----
  1237.   command at the end of the article and the `=' {\fBgoto-menu\fP}
  1238.   returns to the menu immediately as usual.
  1239.   .TP
  1240. + \fBauto-read-mode-limit\fP \fIN\fP    (integer, default 0)
  1241. + When operating in \fIauto reading mode\fP, \fInn\fP will
  1242. + \fIauto-select\fP all unread articles in the group, skip the
  1243. + article selection phase, and enter reading mode directly after
  1244. + entry to the group.
  1245. +   Auto reading mode is disabled when \fBauto-read-mode-limit\fP is
  1246. + zero; it is activated unconditionally if the value is negative, and
  1247. + conditionally if the value is greater than zero and the number of
  1248. + unread articles in the current group does not exceed the given value.
  1249. + .TP
  1250.   \fBauto-select-subject\fP    (boolean, default false)
  1251.   When set, selecting an article from the menu using the article id
  1252.   (a-z), all articles on the menu with the same subject will
  1253. ***************
  1254. *** 315,320 ****
  1255. --- 325,334 ----
  1256.   using a meta-notation \fBM-\fP\fI7bit-char\fP.  If set to 8, these
  1257.   characters are sent directly to the screen (unless \fBmonitor\fP is
  1258.   set).
  1259. + .sp 0.5v
  1260. + It also controls whether keyboard input is 7 or 8 bits, and thus
  1261. + whether key maps contain 127 or 255 entries.  See the key mapping
  1262. + section for more details.
  1263.   .TP
  1264.   \fBdate\fP        (boolean, default true)
  1265.   If set \fInn\fP will show the article posting date when articles are
  1266. ***************
  1267. *** 488,493 ****
  1268. --- 502,519 ----
  1269.   are very difficult to comprehend.  Let's all use the standard folks!
  1270.   (And hack inews if it is the 50% rule that bothers you.)
  1271.   .TP
  1272. + \fBinews\fP \fIshell-command\fP    (string, default "INEWS_PATH -h")
  1273. + The program which is invoked by \fInn\fP to deliver an article to the
  1274. + news transport.  The program will be given a complete article
  1275. + including a header containing the newsgroups to which the article is
  1276. + to be posted.  See also \fBinews-pipe-input\fP.  It is \fInot\fP used
  1277. + when cancelling an article!
  1278. + .TP
  1279. + \fBinews-pipe-input\fP        (boolean, default true)
  1280. + When set, the article to be posted will be piped into the \fBinews\fP
  1281. + program.  Otherwise, the file containing the article will be given as
  1282. + the first (and only) argument to the \fBinews\fP command.
  1283. + .TP
  1284.   \fBkeep-unsubscribed\fP        (boolean, default true)
  1285.   When set, unsubscribed groups are kept in .newsrc.  If not set,
  1286.   \fInn\fP will automatically remove all unsubscribed from .newsrc if
  1287. ***************
  1288. *** 653,658 ****
  1289. --- 679,688 ----
  1290.   format compatible with the \fIrn\fP news reader (\&.rnlast).  This needs
  1291.   to be tested!
  1292.   .TP
  1293. + \fBnew-style-read-prompt\fP    (boolean, default true)
  1294. + When set, the reading mode prompt line includes the group name and the
  1295. + number of selected articles in the group.
  1296. + .TP
  1297.   \fBnews-header\fP \fIheaders\fP    (string, default not set)
  1298.   The \fIheaders\fP string specifies one or more extra header lines
  1299.   (separated by semi-colons `;') which are added to the header of
  1300. ***************
  1301. *** 750,755 ****
  1302. --- 780,791 ----
  1303.   .TP
  1304.   \fBpreview-mark-read\fP        (boolean, default true)
  1305.   When set, previewing an article will mark the article as read.
  1306. + .TP
  1307. + \fBprint-header-type\fP \fIN\fP    (integer, default 1)
  1308. + Specifies what kind of header is printed by the \fB:print\fP command,
  1309. + corresponding to the three \fBsave-*\fP commands: \fI0\fP prints only
  1310. + the article body (no header), \fI1\fP prints a short header,
  1311. + and \fI2\fP prints the full article header.
  1312.   .TP
  1313.   \fBprinter\fP \fIshell-command\fP    (string, default is system dep.)
  1314.   This is the default value for the
  1315. *** ./LAST/man/nn.1.D    Tue Jun 12 11:46:49 1990
  1316. --- man/nn.1.D    Mon Jun 25 15:18:12 1990
  1317. ***************
  1318. *** 544,549 ****
  1319. --- 544,564 ----
  1320.   \fB#0\fP  through  \fB#9\fP
  1321.   These symbols represent the ten user-defined multikeys.
  1322.   .LP
  1323. + If the variable \fBdata-bits\fP is 7, key maps can specify binding of
  1324. + all keys in the range 0x00 to 0x7F, and the 8th bit will be stripped
  1325. + in all keyboard input.
  1326. + If the variable \fBdata-bits\fP is 8, the 8th bit is not cleared, and
  1327. + key maps are extended to allow binding of keys in the range 0xA0 to
  1328. + 0xFE (corresponding to the national characters defined by the ISO 8859
  1329. + character sets).
  1330. + Binding commands to these keys can be done either by using their
  1331. + numeric value, or directly specifying the 8 bit character in the map
  1332. + command, e.g.
  1333. + .sp 0.5v
  1334. +     map menu 0xC8 macro 72
  1335. + .br
  1336. +     map key \o'\(aae' %
  1337. + .LP
  1338.   To show the current contents of the four tables, the following
  1339.   versions of the \fB:map\fP command are available:
  1340.   .TP
  1341. ***************
  1342. *** 891,896 ****
  1343. --- 906,916 ----
  1344.   The commands are executed if the local host's name occur in the
  1345.   \fIhost-name\fP list.
  1346.   .TP
  1347. + \fBon program\fP \fIprogram-name\fP...
  1348. + .br
  1349. + The commands are executed if the current program (\fInn\fP,
  1350. + \fInncheck\fP, etc) in the \fIprogram-name\fP list.
  1351. + .TP
  1352.   \fBon entry\fP [ \fIgroup list\fP ]
  1353.   .br
  1354.   These commands (macro format!) are executed every time \fInn\fP enters a
  1355. ***************
  1356. *** 900,917 ****
  1357.   associated with the groups in the list.  The group list is specified
  1358.   using the meta-notations described in the presentation sequence section.
  1359.   .sp 0.5v
  1360. ! The `:set', `:unset', and `:local' commands at the beginning of the
  1361.   command group are executed \fIbefore\fP \fInn\fP collects the articles
  1362. ! in the group, so it is possible to set variables like
  1363. ! \fBcross-post\fP.  The other commands, and :set/:unset commands that
  1364. ! follows a command of another type will be executed immediately
  1365. ! \fIafter\fP the first menu page is presented.
  1366.   .sp 0.5v
  1367.   .nf
  1368.       \fBon entry\fP comp.sources* alt.sources
  1369. !         :local cross-post on
  1370.       \fBend\fP
  1371.   .fi
  1372.   .SH GROUP PRESENTATION SEQUENCE
  1373.   News groups are normally presented in the sequence defined in the
  1374.   system-wide
  1375. --- 920,949 ----
  1376.   associated with the groups in the list.  The group list is specified
  1377.   using the meta-notations described in the presentation sequence section.
  1378.   .sp 0.5v
  1379. ! \fIAll\fP `:' commands at the beginning of the
  1380.   command group are executed \fIbefore\fP \fInn\fP collects the articles
  1381. ! in the group, so it is possible to set or unset variables like
  1382. ! \fBcross-post\fP and \fBauto-read-mode\fP before any articles are
  1383. ! collected and the menu is (not) shown.
  1384. !   The non-`:' commands, and `:' commands that follows a command of
  1385. ! another type will be executed immediately \fIafter\fP the first menu
  1386. ! page is presented.  The execution of a `:' command can be postponed by
  1387. ! using a double `::' as the command prefix.
  1388.   .sp 0.5v
  1389.   .nf
  1390.       \fBon entry\fP comp.sources* alt.sources
  1391. !         :set cross-post on   # set before collection
  1392. !         :local auto-read-mode on   # set before showing menu
  1393. !         ::unset cross-post   # set after collection
  1394.       \fBend\fP
  1395.   .fi
  1396. + .TP
  1397. + \fBon start-up\fP
  1398. + .br
  1399. + These `:' commands (macro format!) are executed on start-up just
  1400. + before \fInn\fP enters the first news group.  However, postponed
  1401. + commands (i.e. non-`:' commands) will not be executed until the first
  1402. + group is shown (it works like an entry macro).
  1403.   .SH GROUP PRESENTATION SEQUENCE
  1404.   News groups are normally presented in the sequence defined in the
  1405.   system-wide
  1406. *** ./LAST/man/nnmaster.8    Tue May 29 18:36:30 1990
  1407. --- man/nnmaster.8    Mon Jun 25 11:51:52 1990
  1408. ***************
  1409. *** 123,128 ****
  1410. --- 123,137 ----
  1411.   I cannot recommend this unless you receive batched news; invoking
  1412.   \fInnmaster\fP for every received article sounds too expensive to me.)
  1413.   .TP
  1414. + \-\fBh\fP [ \fIsec\fP ]
  1415. + Hold collection of new articles until next scan if new articles have
  1416. + arrived withing the last \fIsec\fP [60] seconds.  This is useful to
  1417. + prevent \fInnmaster\fP from competing for disk i/o with an \fIrnews\fP
  1418. + process which is unbatching incoming news, or a running \fIexpire\fP
  1419. + process.  It will have the side effect of limiting the number of C:
  1420. + entries in the log, since collection of incoming batches will
  1421. + typically be done in larger thunks.
  1422. + .TP
  1423.   .B \-f
  1424.   Run \fInnmaster\fP in foreground in daemon mode (see \-\fBr\fP).
  1425.   Useful if \fInnmaster\fP is invoked from inittab.  (Notice that if you
  1426. *** ./LAST/master.c    Tue Jun 12 11:46:51 1990
  1427. --- master.c    Mon Jun 25 11:54:15 1990
  1428. ***************
  1429. *** 19,24 ****
  1430. --- 19,25 ----
  1431.    *
  1432.    *    -e [N]    expire a group if more than N articles are gone
  1433.    *    -r N    repeat every N minutes
  1434. +  *    -h N    don't update if active file is less than N *seconds* old
  1435.    *
  1436.    *    -f    foreground execution (use with -r)
  1437.    *    -y N    retry N times on error
  1438. ***************
  1439. *** 98,103 ****
  1440. --- 99,105 ----
  1441.       wakeup_master = 0;
  1442.   
  1443.   static unsigned
  1444. +     hold_updates = 0,
  1445.       repeat_delay = 0;
  1446.   
  1447.   
  1448. ***************
  1449. *** 116,121 ****
  1450. --- 118,124 ----
  1451.       'f', Bool_Option( foreground ),
  1452.       'F', Bool_Option( expire_once ),
  1453.       'G', Bool_Option( reread_groups_file ),
  1454. +     'h', Int_Option_Optional( hold_updates, 60 ),
  1455.   #ifdef NNTP
  1456.       'H', Bool_Option( nntp_local_server ),
  1457.   #endif
  1458. ***************
  1459. *** 546,551 ****
  1460. --- 549,555 ----
  1461.       time_t age_active;
  1462.       int group_selection;
  1463.       int temp;
  1464. +     int skip_pass;
  1465.   
  1466.       umask(002);            /* avoid paranoia */
  1467.   
  1468. ***************
  1469. *** 707,718 ****
  1470.           sleep(5);    /* maybe a temporary glitch ? */
  1471.       }
  1472.   
  1473.       if (unconditional) {
  1474. -         master.last_scan = age_active - 60;
  1475.           unconditional = 0;
  1476. !     }
  1477.   
  1478. !     if (!receive_admin() && age_active <= master.last_scan) {
  1479.           if (repeat_delay == 0) break;
  1480.           if (s_hangup) break;
  1481.   #ifdef NNTP
  1482. --- 711,728 ----
  1483.           sleep(5);    /* maybe a temporary glitch ? */
  1484.       }
  1485.   
  1486. +     skip_pass = 0;
  1487. +     
  1488.       if (unconditional) {
  1489.           unconditional = 0;
  1490. !     } else
  1491. !     if (age_active <= master.last_scan ||
  1492. !         (hold_updates && (cur_time() - age_active) < hold_updates))
  1493. !         skip_pass = 1;
  1494. !     if (receive_admin()) skip_pass = 0;
  1495.   
  1496. !     if (skip_pass) {
  1497.           if (repeat_delay == 0) break;
  1498.           if (s_hangup) break;
  1499.   #ifdef NNTP
  1500. *** ./LAST/menu.c    Tue Jun 12 11:46:54 1990
  1501. --- menu.c    Fri Jun 22 00:39:46 1990
  1502. ***************
  1503. *** 35,40 ****
  1504. --- 35,41 ----
  1505.   export int  preview_mark_read = 1; /* previewed articles are A_READ */
  1506.   export int  select_on_sender = 0; /* find command selects on sender */
  1507.   export int  auto_select_subject = 0; /* auto select articles with same subj. */
  1508. + export int  auto_read_limit = 0; /* ignore auto_read_mode if less articles */
  1509.   
  1510.   export char delayed_msg[100] = "";    /* give to msg() after redraw */
  1511.   
  1512. ***************
  1513. *** 323,329 ****
  1514. --- 324,341 ----
  1515.       return 0;
  1516.   }
  1517.   
  1518. + export long n_selected;
  1519.   
  1520. + static count_selected_articles()
  1521. + {
  1522. +     register article_number cur;
  1523. +     n_selected = 0;
  1524. +     for (cur = 0; cur < n_articles; cur++) {
  1525. +     if (articles[cur]->attr & A_SELECT) n_selected++;
  1526. +     }
  1527. + }
  1528.   static show_articles()
  1529.   {
  1530.       register article_number cur, next, temp;
  1531. ***************
  1532. *** 332,337 ****
  1533. --- 344,350 ----
  1534.       register int mode;
  1535.       int cmd, prev = -1, again;
  1536.       attr_type o_attr;
  1537. +     import int new_read_prompt;
  1538.   
  1539.       do {
  1540.       for (cur = 0; cur < n_articles; cur++) {
  1541. ***************
  1542. *** 349,354 ****
  1543. --- 362,370 ----
  1544.           o_attr = ah->attr;
  1545.           ah->attr = 0;
  1546.   
  1547. +         if (new_read_prompt)
  1548. +         count_selected_articles();
  1549.           mode = 0;
  1550.           if (prev >= 0) mode |= MM_PREVIOUS;
  1551.           if (next == n_articles) mode |= MM_LAST_SELECTED;
  1552. ***************
  1553. *** 382,390 ****
  1554.           break;
  1555.   
  1556.            case MC_PREV:
  1557.           if (prev == next) break;
  1558.   
  1559. -         ah->attr = o_attr;
  1560.           next = cur; cur = prev; prev = next;
  1561.           goto show;
  1562.   
  1563. --- 398,406 ----
  1564.           break;
  1565.   
  1566.            case MC_PREV:
  1567. +         ah->attr = o_attr;
  1568.           if (prev == next) break;
  1569.   
  1570.           next = cur; cur = prev; prev = next;
  1571.           goto show;
  1572.   
  1573. ***************
  1574. *** 400,405 ****
  1575. --- 416,422 ----
  1576.           break;
  1577.   
  1578.            case MC_ALLSUBJ:
  1579. +         ah->attr = A_READ;
  1580.           for (next = cur+1; next < n_articles; next++) {
  1581.               ah = articles[next];
  1582.               if ((ah->flag & (A_SAME | A_ALMOST_SAME)) == 0) break;
  1583. ***************
  1584. *** 630,635 ****
  1585. --- 647,654 ----
  1586.       extern int        alt_cmd_key, in_menu_mode;
  1587.       article_number    elim_list[3];
  1588.       int            entry_check;
  1589. +     int            auto_read;
  1590. +     long        o_selected;
  1591.   
  1592.   #define    menu_return(cmd) \
  1593.       { menu_cmd = (cmd); goto menu_exit; }
  1594. ***************
  1595. *** 638,649 ****
  1596.   
  1597.       o_firsta = firsta;
  1598.       o_mode = in_menu_mode;
  1599.       in_menu_mode = 1;
  1600.   
  1601.       menu_level++;
  1602.   
  1603. !     entry_check = menu_level == 1 && conf_group_entry &&
  1604. !     current_group->unread_count > conf_entry_limit;
  1605.   
  1606.       sprintf(pr_fmt,
  1607.           menu_level == 1 ?
  1608. --- 657,675 ----
  1609.   
  1610.       o_firsta = firsta;
  1611.       o_mode = in_menu_mode;
  1612. +     o_selected = n_selected;
  1613.       in_menu_mode = 1;
  1614.   
  1615.       menu_level++;
  1616.   
  1617. !     if (menu_level == 1) {
  1618. !     entry_check = conf_group_entry && n_articles > conf_entry_limit;
  1619. !     auto_read = auto_read_limit < 0 || n_articles <= auto_read_limit;
  1620. !     } else {
  1621. !     entry_check = 0;
  1622. !     auto_read = 0;
  1623. !     }
  1624.   
  1625.       sprintf(pr_fmt,
  1626.           menu_level == 1 ?
  1627. ***************
  1628. *** 690,701 ****
  1629.   
  1630.       clrdisp();
  1631.   
  1632. !     firstl = CALL(print_header)();
  1633. !     if (entry_check && menu_level == 1) {
  1634. !     /* we do it here to avoid redrawing the group header */
  1635. !     entry_check = 0;
  1636. !     prompt_line = firstl;
  1637.       prompt("\1Enter?\1 ");
  1638.       if ((temp = yes(0)) <= 0) {
  1639.           if (temp < 0) {
  1640. --- 716,723 ----
  1641.   
  1642.       clrdisp();
  1643.   
  1644. !     if (entry_check) {
  1645. !     prompt_line = firstl = CALL(print_header)();
  1646.       prompt("\1Enter?\1 ");
  1647.       if ((temp = yes(0)) <= 0) {
  1648.           if (temp < 0) {
  1649. ***************
  1650. *** 710,715 ****
  1651. --- 732,752 ----
  1652.       clrline();
  1653.       }
  1654.   
  1655. +     if (auto_read) {
  1656. +     auto_read = entry_check = 0;
  1657. +     if (repl_attr_all(0, A_AUTO_SELECT, 0)) {
  1658. +         k_cmd = K_READ_GROUP_UPDATE;
  1659. +         sprintf(delayed_msg, "Entering %s, %ld articles",
  1660. +             current_group->group_name, (long)n_articles);
  1661. +         goto do_auto_read;
  1662. +     }
  1663. +     }
  1664. +     if (!entry_check)
  1665. +     firstl = CALL(print_header)();
  1666. +     entry_check = 0;
  1667.       maxa = Lines - preview_window - firstl - 2;
  1668.       if (!long_menu) firstl++, maxa -= 2;
  1669.   
  1670. ***************
  1671. *** 1539,1544 ****
  1672. --- 1576,1582 ----
  1673.   
  1674.       no_raw();
  1675.   
  1676. +  do_auto_read:
  1677.       switch (show_articles()) {
  1678.   
  1679.        case MC_MENU:
  1680. ***************
  1681. *** 1569,1574 ****
  1682. --- 1607,1613 ----
  1683.   
  1684.    menu_exit:
  1685.   
  1686. +     n_selected = o_selected;
  1687.       firsta = o_firsta;
  1688.       in_menu_mode = o_mode;
  1689.       menu_level--;
  1690. *** ./LAST/more.c    Tue Jun 12 11:46:56 1990
  1691. --- more.c    Fri Jun 22 00:39:46 1990
  1692. ***************
  1693. *** 24,29 ****
  1694. --- 24,30 ----
  1695.   export int  scroll_clear_page = 1;
  1696.   export int  expired_msg_delay = 1;
  1697.   export char *trusted_escapes = NULL;
  1698. + export int  new_read_prompt = 1;
  1699.   
  1700.   import int  preview_window;
  1701.   import int  novice;
  1702. ***************
  1703. *** 115,121 ****
  1704.       *cp++ = 'l';
  1705.       }
  1706.   
  1707. !     strcpy(cp, ")------");
  1708.       return buf;
  1709.   }
  1710.   
  1711. --- 116,122 ----
  1712.       *cp++ = 'l';
  1713.       }
  1714.   
  1715. !     strcpy(cp, new_read_prompt ? ")--" : ")------");
  1716.       return buf;
  1717.   }
  1718.   
  1719. ***************
  1720. *** 224,229 ****
  1721. --- 225,249 ----
  1722.   
  1723.       stop_line = first_page_lines ? first_page_lines : -1;
  1724.   
  1725. +     if (new_read_prompt) {
  1726. +     import long n_selected;
  1727. +     if (mode & (MM_PREVIEW | MM_DIGEST) || n_selected == 0)
  1728. +         sprintf(pr_fmt,
  1729. +             "\1\2--%s-- %s%s %s--%%s--%%s\1",
  1730. +             current_group->group_name,
  1731. +             (mode & MM_DIGEST) ? "DIGEST" :
  1732. +             (mode & MM_PREVIEW) ? "PREVIEW" : "LAST",
  1733. +             (ah->flag & A_NEXT_SAME) ? "+next" : "",
  1734. +             novice ? "--help:?" : "");
  1735. +     else
  1736. +         sprintf(pr_fmt,
  1737. +             "\1\2--%s-- %ld MORE%s %s--%%s--%%s\1",
  1738. +             current_group->group_name,
  1739. +             n_selected,
  1740. +             (ah->flag & A_NEXT_SAME) ? "+next" : "",
  1741. +             novice ? "--help:?" : "");
  1742. +     } else
  1743.       sprintf(pr_fmt,
  1744.           "\1\2-- %s%s %s-----%%s%s-----%%s\1",
  1745.           (mode & MM_PREVIEW) ? "PREVIEW " : "",
  1746. *** ./LAST/newsrc.c    Tue Jun 12 11:46:58 1990
  1747. --- newsrc.c    Tue Jun 19 23:28:33 1990
  1748. ***************
  1749. *** 223,228 ****
  1750. --- 223,230 ----
  1751.       register int i;
  1752.       struct stat st;
  1753.   
  1754. +     if (no_update) return;
  1755.       if (new_group_action == RCX_RNLAST) {
  1756.       lf = open_file(rnlast_path, OPEN_CREATE|MUST_EXIST);
  1757.       fputs(rnlast_line[RN_LAST_GROUP_READ], lf);    /* as good as any */
  1758. ***************
  1759. *** 406,412 ****
  1760.           if (last_new_gh == NULL || last_new_gh->creation_time <= gh->creation_time)
  1761.               last_new_gh = gh;
  1762.   
  1763. !         if (new_group_action != RCX_TIME) {
  1764.               printf("\nNew group: %s -- append to .newsrc? (y)",
  1765.                  gh->group_name);
  1766.               if (yes(0) <= 0) continue;
  1767. --- 408,414 ----
  1768.           if (last_new_gh == NULL || last_new_gh->creation_time <= gh->creation_time)
  1769.               last_new_gh = gh;
  1770.   
  1771. !         if (new_group_action != RCX_TIME && !no_update) {
  1772.               printf("\nNew group: %s -- append to .newsrc? (y)",
  1773.                  gh->group_name);
  1774.               if (yes(0) <= 0) continue;
  1775. ***************
  1776. *** 1494,1500 ****
  1777.       total = groups = 0;
  1778.   
  1779.       if (goback_interact) {
  1780. -     init_term(1);
  1781.       raw();
  1782.       }
  1783.   
  1784. --- 1496,1501 ----
  1785. *** ./LAST/nn.c    Tue Jun 12 11:46:59 1990
  1786. --- nn.c    Thu Jun 21 17:25:40 1990
  1787. ***************
  1788. *** 160,165 ****
  1789. --- 160,168 ----
  1790.       gh = group_sequence;
  1791.       after_loop = NULL;
  1792.   
  1793. +     if (access_mode == 0 && !also_read_articles)
  1794. +     m_invoke(-2);
  1795.       for (;;) {
  1796.       group_mode = access_mode;
  1797.       
  1798. ***************
  1799. *** 658,663 ****
  1800. --- 661,667 ----
  1801.       }
  1802.   
  1803.       visit_init_file(0, argv[1]);
  1804. +     init_answer();
  1805.   
  1806.       group_name_args =
  1807.           parse_options(argc, argv, (char *)NULL, nn_options,
  1808. ***************
  1809. *** 717,722 ****
  1810. --- 721,727 ----
  1811.       group_name_args =
  1812.           parse_options(argc, argv, (char *)NULL, check_options,
  1813.                 " [group]...");
  1814. +     no_update = 1;        /* don't update .newsrc and LAST */
  1815.       break;
  1816.   
  1817.        case I_AM_EMACS:
  1818. ***************
  1819. *** 724,742 ****
  1820.       break;
  1821.   
  1822.        case I_AM_TIDY:
  1823. !     init_term(0);
  1824.       visit_init_file(0, (char *)NULL);
  1825.       group_name_args = opt_nntidy(argc, argv);
  1826.       break;
  1827.   
  1828.        case I_AM_GOBACK:
  1829.       group_name_args = opt_nngoback(argc, &argv);
  1830.       break;
  1831.   
  1832.        case I_AM_GREP:
  1833.       visit_init_file(0, (char *)NULL);
  1834.       opt_nngrep(argc, argv);
  1835.       silent = 1;
  1836.       break;
  1837.   
  1838.        case I_AM_POST:
  1839. --- 729,751 ----
  1840.       break;
  1841.   
  1842.        case I_AM_TIDY:
  1843. !     init_term(1);
  1844.       visit_init_file(0, (char *)NULL);
  1845.       group_name_args = opt_nntidy(argc, argv);
  1846.       break;
  1847.   
  1848.        case I_AM_GOBACK:
  1849. +     init_term(1);
  1850. +     visit_init_file(0, (char *)NULL);
  1851.       group_name_args = opt_nngoback(argc, &argv);
  1852.       break;
  1853.   
  1854.        case I_AM_GREP:
  1855. +     init_term(0);
  1856.       visit_init_file(0, (char *)NULL);
  1857.       opt_nngrep(argc, argv);
  1858.       silent = 1;
  1859. +     no_update = 1;
  1860.       break;
  1861.   
  1862.        case I_AM_POST:
  1863. *** ./LAST/patchlevel.h    Tue Jun 12 11:47:00 1990
  1864. --- patchlevel.h    Fri Jun 22 14:37:22 1990
  1865. ***************
  1866. *** 16,22 ****
  1867.    *    1990-05-21: Patch #3 (6.4.3) - HIGH
  1868.    *    1990-05-29: Patch #4 (6.4.4) - HIGH
  1869.    *    1990-06-11: Patch #5 (6.4.5) - MEDIUM
  1870.    */
  1871.   
  1872. ! #define PATCHLEVEL 5
  1873.   
  1874. --- 16,23 ----
  1875.    *    1990-05-21: Patch #3 (6.4.3) - HIGH
  1876.    *    1990-05-29: Patch #4 (6.4.4) - HIGH
  1877.    *    1990-06-11: Patch #5 (6.4.5) - MEDIUM
  1878. +  *    1990-06-25: Patch #6 (6.4.6) - MEDIUM
  1879.    */
  1880.   
  1881. ! #define PATCHLEVEL 6
  1882.   
  1883. *** ./LAST/save.c    Tue May 29 18:36:38 1990
  1884. --- save.c    Fri Jun 22 12:07:07 1990
  1885. ***************
  1886. *** 48,57 ****
  1887.   #define    HEADER_HANDLING    0x0f    /* what should we do with the header */
  1888.   
  1889.   #define NO_HEADER    0    /* save without a header */
  1890. ! #define    FULL_HEADER    1    /* save with full header */
  1891. ! #define SHORT_HEADER    2    /* save with partial header */
  1892.   #define    SHORT_HEADER_DG    3    /* save with partial header (digest) */
  1893.   
  1894.   
  1895.   #define    SEPARATE_FILES    0x0100    /* save as separate files */
  1896.   #define UNIQUE_FILES    0x0200    /* save in unique files */
  1897. --- 48,58 ----
  1898.   #define    HEADER_HANDLING    0x0f    /* what should we do with the header */
  1899.   
  1900.   #define NO_HEADER    0    /* save without a header */
  1901. ! #define SHORT_HEADER    1    /* save with partial header */
  1902. ! #define    FULL_HEADER    2    /* save with full header */
  1903.   #define    SHORT_HEADER_DG    3    /* save with partial header (digest) */
  1904.   
  1905. + export int print_header_type = SHORT_HEADER;
  1906.   
  1907.   #define    SEPARATE_FILES    0x0100    /* save as separate files */
  1908.   #define UNIQUE_FILES    0x0200    /* save in unique files */
  1909. ***************
  1910. *** 66,73 ****
  1911.   
  1912.   static int open_mode[] = {
  1913.       SKIP_HEADER,
  1914. -     0,
  1915.       FILL_NEWS_HEADER | SKIP_HEADER,
  1916.       FILL_DIGEST_HEADER | SKIP_HEADER
  1917.   };
  1918.   
  1919. --- 67,74 ----
  1920.   
  1921.   static int open_mode[] = {
  1922.       SKIP_HEADER,
  1923.       FILL_NEWS_HEADER | SKIP_HEADER,
  1924. +     0,
  1925.       FILL_DIGEST_HEADER | SKIP_HEADER
  1926.   };
  1927.   
  1928. ***************
  1929. *** 291,298 ****
  1930.       break;
  1931.   
  1932.        case K_PRINT:
  1933. !     save_mode = SHORT_HEADER | IS_PIPE;
  1934.   
  1935.       if (!shell_restrictions && edit_print_command) {
  1936.           prompt("\1Print command:\1 ");
  1937.           save_name = get_s(NONE, printer, NONE, NULL_FCT);
  1938. --- 292,304 ----
  1939.       break;
  1940.   
  1941.        case K_PRINT:
  1942. !     if (print_header_type < NO_HEADER || print_header_type > FULL_HEADER) {
  1943. !         msg("Invalid 'print-header-type' value %d", print_header_type);
  1944. !         print_header_type = NO_HEADER;
  1945. !     }
  1946.   
  1947. +     save_mode = print_header_type | IS_PIPE;
  1948. +     
  1949.       if (!shell_restrictions && edit_print_command) {
  1950.           prompt("\1Print command:\1 ");
  1951.           save_name = get_s(NONE, printer, NONE, NULL_FCT);
  1952. ***************
  1953. *** 384,389 ****
  1954. --- 390,396 ----
  1955.       int was_raw = 0, set_visual = 0;
  1956.       char copybuf[FILENAME * 4], uniqbuf[FILENAME];
  1957.       flag_type st_flag = A_ST_FILED;
  1958. +     int with_header;
  1959.   
  1960.       if (ah->a_group) init_group(ah->a_group);
  1961.   
  1962. ***************
  1963. *** 474,480 ****
  1964.       clrline();
  1965.       s_pipe = 0;
  1966.   
  1967. !     if (mode != NO_HEADER)
  1968.       mailbox_format(save_file, 1);
  1969.   
  1970.       if (mode == FULL_HEADER) {
  1971. --- 481,490 ----
  1972.       clrline();
  1973.       s_pipe = 0;
  1974.   
  1975. !     with_header = mode != NO_HEADER &&
  1976. !     (save_mode & (IS_PIPE | DO_UNSHAR)) == 0;
  1977. !     if (with_header)
  1978.       mailbox_format(save_file, 1);
  1979.   
  1980.       if (mode == FULL_HEADER) {
  1981. ***************
  1982. *** 506,524 ****
  1983.       fflush(save_file);
  1984.       if (s_pipe) goto broken_pipe;
  1985.   
  1986. -     mode = mode != NO_HEADER && (save_mode & (IS_PIPE | DO_UNSHAR)) == 0;
  1987.       lcount = 0;
  1988.       while (ftell(art) < ah->lpos && fgets(copybuf, 512, art)) {
  1989.       lcount++;
  1990.       if (rot13_active) rot13_line(copybuf);
  1991. !     if (mode && is_header_line(copybuf))
  1992.           fputc('~', save_file);
  1993.       fputs(copybuf, save_file);
  1994.       if (s_pipe) goto broken_pipe;
  1995.       }
  1996.   
  1997. !     if (mode != NO_HEADER)
  1998.       lcount += mailbox_format(save_file, 0);
  1999.   
  2000.   broken_pipe:
  2001. --- 516,532 ----
  2002.       fflush(save_file);
  2003.       if (s_pipe) goto broken_pipe;
  2004.   
  2005.       lcount = 0;
  2006.       while (ftell(art) < ah->lpos && fgets(copybuf, 512, art)) {
  2007.       lcount++;
  2008.       if (rot13_active) rot13_line(copybuf);
  2009. !     if (with_header && is_header_line(copybuf))
  2010.           fputc('~', save_file);
  2011.       fputs(copybuf, save_file);
  2012.       if (s_pipe) goto broken_pipe;
  2013.       }
  2014.   
  2015. !     if (with_header)
  2016.       lcount += mailbox_format(save_file, 0);
  2017.   
  2018.   broken_pipe:
  2019. *** ./LAST/term.c    Tue Jun 12 11:47:02 1990
  2020. --- term.c    Fri Jun 22 23:09:47 1990
  2021. ***************
  2022. *** 20,25 ****
  2023. --- 20,27 ----
  2024.   extern int s_resized;
  2025.   #endif
  2026.   
  2027. + import int data_bits;
  2028.   struct msg_list {
  2029.       char *buf;
  2030.       struct msg_list *prev;
  2031. ***************
  2032. *** 408,415 ****
  2033.       raw_tty = norm_tty;
  2034.   
  2035.   #ifdef HAVE_TERMIO
  2036. !     raw_tty.c_iflag &= ~(BRKINT|INLCR|ICRNL|IGNCR);
  2037. !     raw_tty.c_iflag |= IGNBRK|IGNPAR|ISTRIP;
  2038.       raw_tty.c_oflag &= ~OPOST;
  2039.       raw_tty.c_lflag &= ~(ISIG|ICANON|XCASE|ECHO|NOFLSH);
  2040.   
  2041. --- 410,417 ----
  2042.       raw_tty = norm_tty;
  2043.   
  2044.   #ifdef HAVE_TERMIO
  2045. !     raw_tty.c_iflag &= ~(BRKINT|INLCR|ICRNL|IGNCR|ISTRIP);
  2046. !     raw_tty.c_iflag |= IGNBRK|IGNPAR;
  2047.       raw_tty.c_oflag &= ~OPOST;
  2048.       raw_tty.c_lflag &= ~(ISIG|ICANON|XCASE|ECHO|NOFLSH);
  2049.   
  2050. ***************
  2051. *** 866,874 ****
  2052.       arm_fake_keyb_sig = 1;
  2053.   #endif
  2054.       while ((n = read(0, (char *)&c, 1)) > 0) {
  2055. -     c &= 0177;    /* done by ISTRIP on USG systems */
  2056.   #endif
  2057.   
  2058.       if (ignore_xon_xoff && (c == CONTROL_('Q') || c == CONTROL_('S')))
  2059.           continue;
  2060.   
  2061. --- 868,877 ----
  2062.       arm_fake_keyb_sig = 1;
  2063.   #endif
  2064.       while ((n = read(0, (char *)&c, 1)) > 0) {
  2065.   #endif
  2066.   
  2067. +     if (data_bits < 8) c &= 0x7f;
  2068.       if (ignore_xon_xoff && (c == CONTROL_('Q') || c == CONTROL_('S')))
  2069.           continue;
  2070.   
  2071. ***************
  2072. *** 987,996 ****
  2073.   char *dflt, *prefill, *break_chars;
  2074.   fct_type completion;
  2075.   {
  2076. !     static char buf[GET_S_BUFFER];
  2077.       register char *cp;
  2078.       register int i, c, lastc;
  2079. !     char *ret_val = buf;
  2080.       int comp_used, comp_len;
  2081.       int ostop, max, did_help;
  2082.       int hit_count;
  2083. --- 990,999 ----
  2084.   char *dflt, *prefill, *break_chars;
  2085.   fct_type completion;
  2086.   {
  2087. !     static key_type buf[GET_S_BUFFER];
  2088.       register char *cp;
  2089.       register int i, c, lastc;
  2090. !     char *ret_val = (char *)buf;
  2091.       int comp_used, comp_len;
  2092.       int ostop, max, did_help;
  2093.       int hit_count;
  2094. ***************
  2095. *** 999,1005 ****
  2096.        case 0:
  2097.       break;
  2098.        case 1:
  2099. !     return buf;
  2100.        case 2:
  2101.       return NULL;
  2102.       }
  2103. --- 1002,1008 ----
  2104.        case 0:
  2105.       break;
  2106.        case 1:
  2107. !     return (char *)buf;
  2108.        case 2:
  2109.       return NULL;
  2110.       }
  2111. ***************
  2112. *** 1178,1183 ****
  2113. --- 1181,1189 ----
  2114.           break;
  2115.       }
  2116.   
  2117. +     if (data_bits == 8) {
  2118. +         if (!iso8859(c)) continue;
  2119. +     } else
  2120.       if (!isascii(c) || !isprint(c)) continue;
  2121.   
  2122.       if (i == max) continue;
  2123. ***************
  2124. *** 1209,1214 ****
  2125. --- 1215,1221 ----
  2126.       if (str == NULL) {
  2127.       cols = Columns;
  2128.       line = prompt_line + 1;
  2129. +     if (line == Lines - 1) cols--;
  2130.   
  2131.       gotoxy(0, line);
  2132.       clrpage(line);
  2133. *** ./LAST/variable.c    Tue Jun 12 11:47:03 1990
  2134. --- variable.c    Fri Jun 22 12:09:01 1990
  2135. ***************
  2136. *** 22,27 ****
  2137. --- 22,28 ----
  2138.       *header_lines,
  2139.       *folder_directory,
  2140.       included_mark[],
  2141. +     *inews_program,
  2142.       *mail_box,
  2143.       *mail_record,
  2144.       *mail_script,
  2145. ***************
  2146. *** 74,79 ****
  2147. --- 75,81 ----
  2148.       include_art_id,
  2149.       include_full_header,
  2150.       include_mark_blanks,
  2151. +     inews_pipe_input,
  2152.       keep_rc_backup,
  2153.       keep_unsubscribed,
  2154.       keep_unsub_long,
  2155. ***************
  2156. *** 83,88 ****
  2157. --- 85,91 ----
  2158.       mark_overlap,
  2159.       match_parts_equal,
  2160.       monitor_mode,
  2161. +     new_read_prompt,
  2162.       novice,
  2163.       preview_mark_read,
  2164.       query_signature,
  2165. ***************
  2166. *** 112,117 ****
  2167. --- 115,121 ----
  2168.   import int            /* integer variables */
  2169.       also_read_articles,
  2170.       article_limit,
  2171. +     auto_read_limit,
  2172.       conf_entry_limit,
  2173.       collapse_subject,
  2174.       Columns,
  2175. ***************
  2176. *** 136,141 ****
  2177. --- 140,146 ----
  2178.       overlap,
  2179.       preview_continuation,
  2180.       preview_window,
  2181. +     print_header_type,
  2182.       re_layout,
  2183.       response_check_pause,
  2184.       retry_on_error,
  2185. ***************
  2186. *** 199,204 ****
  2187. --- 204,210 ----
  2188.       "attributes",        STR 1,        (char **)attributes,
  2189.       "auto-junk-seen",        BOOL 0,        (char **)&auto_junk_seen,
  2190.       "auto-preview-mode",    BOOL 0,        (char **)&auto_preview_mode,
  2191. +     "auto-read-mode-limit",    INT 0,        (char **)&auto_read_limit,
  2192.       "auto-select-subject",    BOOL 0,        (char **)&auto_select_subject,
  2193.       "backup",            BOOL 0,        (char **)&keep_rc_backup,
  2194.       "backup-suffix",        STR 0,        (char **)&bak_suffix,
  2195. ***************
  2196. *** 248,253 ****
  2197. --- 254,261 ----
  2198.       "include-full-header",    BOOL 0,        (char **)&include_full_header,
  2199.       "include-mark-blank-lines",    BOOL 0,        (char **)&include_mark_blanks,
  2200.       "included-mark",        STR 1,        (char **)included_mark,
  2201. +     "inews",            STR 0,        (char **)&inews_program,
  2202. +     "inews-pipe-input",        BOOL 0,        (char **)&inews_pipe_input,
  2203.       "keep-unsubscribed",     BOOL 0,        (char **)&keep_unsubscribed,
  2204.       "kill",            BOOL 0,        (char **)&do_kill_handling,
  2205.       "kill-debug",        BOOL 0,        (char **)&kill_debug,
  2206. ***************
  2207. *** 273,278 ****
  2208. --- 281,287 ----
  2209.       "mmdf-format",        BOOL 0,        (char **)&use_mmdf_folders,
  2210.       "monitor",            BOOL 0,        (char **)&monitor_mode,
  2211.       "new-group-action",        INT 0,        (char **)&new_group_action,
  2212. +     "new-style-read-prompt",    BOOL 0,        (char **)&new_read_prompt,
  2213.       "news-header",        STR 0,        (char **)&extra_news_headers,
  2214.       "news-record",        STR 2,        (char **)&news_record,
  2215.       "news-script",        STR SAFE 2,    (char **)&news_script,
  2216. ***************
  2217. *** 290,295 ****
  2218. --- 299,305 ----
  2219.       "patch-command",        STR SAFE 1,    (char **)patch_command,
  2220.       "preview-continuation",     INT 0,        (char **)&preview_continuation,
  2221.       "preview-mark-read",    BOOL 0,        (char **)&preview_mark_read,
  2222. +     "print-header-type",    INT 0,        (char **)&print_header_type,
  2223.       "printer",            STR SAFE 1,    (char **)printer,
  2224.       "query-signature",        BOOL 0,        (char **)&query_signature,
  2225.       "quick-count",        BOOL 0,        (char **)&quick_unread_count,
  2226.